/*
   @Copyright:LibreOJ
   @Author:   tjyemail
   @Problem:  https://loj.ac/problem/101
   @Language: C++
   @Datetime: 20-08-14 14:07
   */
// shortest arguement path(SAP), time O(E*V^2) 23ms

#include <bits/stdc++.h>
using namespace std;

#define VERTEX 102
int paths[VERTEX]; // pre-node
int deeps[VERTEX]; // label level
int curs[VERTEX]; // current available edge position
int gaps[VERTEX]; // label k's count
long long caps[VERTEX][VERTEX]; // a->b capacity

void sap(int v, int s, int t) {
	long long flow = 0, cur = 0;
	gaps[0] = v, paths[s] = s;
	for(int a=s, b=0; deeps[s]<v; ) {
		// find available edge a->b
		bool found = false;
		for(b=curs[a]-1; !found && b++<v; )
			found = deeps[a]==deeps[b]+1 && caps[a][b]>0;
		if (found) {
			paths[b] = a; // record b's pre-node a
			curs[a] = b; // current available edge position
			a = b;
			if (b == t) { // found arguement path
				// find current available flow
				for(cur=INT_MAX; a!=s; a=paths[a])
					cur=min(cur, caps[paths[a]][a]);
				// update available capacity
				for(a=t; a!=s; a=paths[a]) {
					caps[paths[a]][a] -= cur;
					caps[a][paths[a]] += cur; // reverse edge
				}
				flow += cur;
				//a = s; // find new arguement path
			}
		} else { // can't find available edge
			if (--gaps[deeps[a]] == 0) break; // has gap => no arguement path
			// back to pre-node and refind arguement path
			int md = v;
			for(b=0; b++<v; ) {
				if (caps[a][b]>0 && md>deeps[b])
					md = deeps[b];
			}
			gaps[deeps[a]=md+1]++;
			curs[a] = 1;
			a = paths[a];
		}
	}
	printf("%lld\n", flow);
}

int main()
{
	int v, e, s, t, a, b, c; // vertex edge, source -> target
	scanf("%d %d %d %d", &v, &e, &s, &t);
	for(int i=0; i++<e; ) {
		scanf("%d %d %d", &a, &b, &c); // a->b, capacity
		caps[a][b] += c; // a->b may have more than one edge
	}
	sap(v, s, t);
	return 0;
}
